package com.utils

import android.util.ArrayMap
import com.tencent.mmkv.MMKV
import com.tencent.mmkv.MMKVHandler
import com.tencent.mmkv.MMKVLogLevel
import com.tencent.mmkv.MMKVRecoverStrategic
import java.io.File

/**
 * 使用腾讯mmkv
 */
object SPUtils {
    private const val TAG = "SPUtils"

    /**
     * 保存资源名称
     */
    private const val MMKV_ID = "mmkv"
    private const val MMKV_CRYPTKEY = "qW7aS9x3HctV3HwDFbIG3Q=="//秘钥
    private const val MMKV_NAME = "mmkv"

    private val mIdMap: ArrayMap<String, MMKV> = ArrayMap()

    init {
        val cacheDir = PathUtils.getCacheDir() + File.separator + MMKV_NAME
        val initialize =
                MMKV.initialize(cacheDir, if (BuildConfig.DEBUG) MMKVLogLevel.LevelDebug else MMKVLogLevel.LevelNone)
        LogUtils.i(TAG, "mmkv root:$initialize")
        MMKV.registerHandler(object :MMKVHandler{
            override fun onMMKVCRCCheckFail(p0: String?): MMKVRecoverStrategic {
                // 校验失败，直接丢弃，不恢复
                return MMKVRecoverStrategic.OnErrorDiscard
            }

            override fun onMMKVFileLengthError(p0: String?): MMKVRecoverStrategic {
                // 校验失败，直接丢弃，不恢复
                return MMKVRecoverStrategic.OnErrorDiscard
            }

            override fun wantLogRedirecting(): Boolean {
                return true
            }

            override fun mmkvLog(level: MMKVLogLevel?, file: String, line: Int, func: String, message: String) {
                val log = "<$file:$line::$func> $message"
                when (level) {
                    MMKVLogLevel.LevelDebug -> {
                        LogUtils.d(TAG, log)
                    }
                    MMKVLogLevel.LevelInfo -> {
                        LogUtils.i(TAG, log)
                    }
                    MMKVLogLevel.LevelWarning -> {
                        LogUtils.w(TAG, log)
                    }
                    MMKVLogLevel.LevelError -> {
                        LogUtils.e(TAG, log)
                    }
                    MMKVLogLevel.LevelNone -> {
                    }
                }
            }

        })
    }

    /**************************默认数据存储空间******************************/
    fun put(key: String, value: String) {
        return put(MMKV_ID, key, value)
    }

    fun put(key: String, value: Int) {
        return put(MMKV_ID, key, value)
    }

    fun put(key: String, value: Boolean) {
        return put(MMKV_ID, key, value)
    }

    fun put(key: String, value: Float) {
        return put(MMKV_ID, key, value)
    }

    fun put(key: String, value: Long) {
        return put(MMKV_ID, key, value)
    }

    fun put(key: String, value: Set<String>) {
        return put(MMKV_ID, key, value)
    }

    fun getString(key: String, defaultString: String): String {
        return getString(MMKV_ID, key, defaultString)
    }

    fun getInt(key: String, defaultInt: Int): Int {
        return getInt(MMKV_ID, key, defaultInt)
    }

    fun getBoolean(key: String, defaultBoolean: Boolean): Boolean {
        return getBoolean(MMKV_ID, key, defaultBoolean)
    }

    fun getFloat(key: String, defaultFloat: Float): Float {
        return getFloat(MMKV_ID, key, defaultFloat)
    }

    fun getLong(key: String, defaultLong: Long): Long {
        return getLong(MMKV_ID, key, defaultLong)
    }

    fun getStringSet(key: String, defaultSet: Set<String>): Set<String>? {
        return getStringSet(MMKV_ID, key, defaultSet)
    }

    /***************************根据id区分存储空间**********************************/
    fun put(id: String, key: String, value: String) {
        getMMKV(id)?.encode(key, value)
    }

    fun put(id: String, key: String, value: Int) {
        getMMKV(id)?.encode(key, value)
    }

    fun put(id: String, key: String, value: Boolean) {
        getMMKV(id)?.encode(key, value)
    }

    fun put(id: String, key: String, value: Float) {
        getMMKV(id)?.encode(key, value)
    }

    fun put(id: String, key: String, value: Long) {
        getMMKV(id)?.encode(key, value)
    }

    fun put(id: String, key: String, value: Set<String>) {
        getMMKV(id)?.encode(key, value)
    }

    fun getString(id: String, key: String, defaultString: String): String {
        return try {
            getMMKV(id)?.decodeString(key, defaultString) ?: defaultString
        } catch (e: Exception) {
            defaultString
        }
    }

    fun getInt(id: String, key: String, defaultInt: Int): Int {
        return try {
            getMMKV(id)?.decodeInt(key, defaultInt) ?: defaultInt
        } catch (e: Exception) {
            defaultInt
        }
    }

    fun getBoolean(id: String, key: String, defaultBoolean: Boolean): Boolean {
        return try {
            getMMKV(id)?.decodeBool(key, defaultBoolean) ?: defaultBoolean
        } catch (e: Exception) {
            defaultBoolean
        }
    }

    fun getFloat(id: String, key: String, defaultFloat: Float): Float {
        return try {
            getMMKV(id)?.decodeFloat(key, defaultFloat) ?: defaultFloat
        } catch (e: Exception) {
            defaultFloat
        }
    }

    fun getLong(id: String, key: String, defaultLong: Long): Long {
        return try {
            getMMKV(id)?.decodeLong(key, defaultLong) ?: defaultLong
        } catch (e: Exception) {
            defaultLong
        }
    }

    fun getStringSet(id: String, key: String, defaultSet: Set<String>): Set<String>? {
        return try {
            getMMKV(id)?.decodeStringSet(key, defaultSet)
        } catch (e: Exception) {
            defaultSet
        }
    }

    fun remove(key: String) {
        remove(MMKV_ID, key)
    }

    fun remove(id: String, key: String) {
        getMMKV(id)?.removeValueForKey(key)
    }

    /**
     * 清除默认存储空间中数据
     *
     */
    fun clearAll() {
        clearAll(MMKV_ID)
    }

    /**
     * 根据id清除所有数据
     *
     * @param id
     */
    fun clearAll(id: String) {
        try {
            getMMKV(id)?.clearAll()
        } catch (e: Exception) {
        }
    }

    private fun getMMKV(id: String): MMKV? {
        return if (id.isNullOrEmpty()) {
            if (mIdMap[MMKV_ID] == null) {
                createMMKV(MMKV_ID)
            }
            mIdMap[MMKV_ID]
        } else {
            if (mIdMap[id] == null) {
                createMMKV(id)
            }
            mIdMap[id]
        }

    }

    private fun createMMKV(id: String): MMKV? {
        val mmkvWithID = MMKV.mmkvWithID(id, MMKV.MULTI_PROCESS_MODE, MMKV_CRYPTKEY)
        mIdMap[MMKV_ID] = mmkvWithID
        return mmkvWithID
    }

    fun onTerminate() {
        mIdMap.clear()
    }
}